/*
 * EvolutionFrame.java
 *
 * Created on den 29 oktober 2007, 22:53
 */
package grex.Graphics;

import grex.ErrorManager;
import grex.EvolutionListener;
import grex.EvolutionProcess;
import grex.FileOutputHandler;
import grex.GP;
import grex.GoogleMailer;
import grex.Options;
import grex.SimplificationListener;
import grex.Simplyfier;
import grex.genes.GeneException;

import java.awt.Component;
import java.awt.FileDialog;
import java.io.File;
import java.util.ArrayList;
import java.util.Calendar;

import javax.mail.MessagingException;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

/**
 *
 * @author  RIK
 */
public class ExternalEvolutionFrame extends javax.swing.JFrame implements EvolutionListener, SimplificationListener {

    /** Creates new form EvolutionFrame */
    EvolutionProcess ep;
    Options options;
    TreePanel lastPanel, lastSimpPanel;
    ArrayList<TreePanel> treePanels;
    int numberOfRuns = 0;

    public ExternalEvolutionFrame(EvolutionProcess ep, Options options) {
        initComponents();
        jbtnSimplify.setVisible(false);
        jbtnOptimize.setVisible(false);
        jbtnStart.setVisible(false);
        jbtnStop.setVisible(false);
        jbtnShowPrediction.setVisible(false);
        this.options = options;
        this.ep = ep;
        ep.addEvolutionListener(this);
        ep.addSimplificationListener(this);
        jtxaOptions.setText(options.toString());
        if (false && options.getPROBLEM_TYPE() != Options.REGRESSION) {
            jbtnShowPrediction.setVisible(false);
        }
        this.setTitle(options.getDATA_FILE());
    }

    private void addNewEvolutionTab(String title) {
        if (lastPanel != null) {
            ep.removeEvolutionLister(lastPanel);
        }
        lastPanel = new TreePanel(null, "",ep.getEnvironment().getErrorCalculator());
        ep.addEvolutionListener(lastPanel);
        jTabbedPane.addTab(title, new CloseTabIcon(), lastPanel);
        jTabbedPane.setSelectedComponent(lastPanel);
        jTabbedPane.validate();

    }

     private void addNewPerformanceTab(String title) {

        PerformancePanel pp = new PerformancePanel();
        ep.addEvolutionListener(pp);
        jTabbedPane.addTab(title, new CloseTabIcon(), pp);
        jTabbedPane.setSelectedComponent(pp);
        jTabbedPane.validate();

    }

    private void addNewOptimizationTab(TreePanel panel) {

        GP gp = (GP) panel.getGP().clone();

        TreePanel p = new TreePanel(gp, "Optimized GP",ep.getEnvironment().getErrorCalculator());
        String titel = jTabbedPane.getTitleAt(jTabbedPane.indexOfComponent(panel));
        jTabbedPane.addTab("O(" + titel + ")", new CloseTabIcon(), p);
        jTabbedPane.setSelectedComponent(p);
        jTabbedPane.validate();
        p.update();


    }

    private void addBatchResultTab(EvolutionProcess ep) {
        JPanel jpnlResult = new JPanel();
        JScrollPane jScrollPaneResult = new JScrollPane();
        JTextArea jtxaResult = new JTextArea();
        jpnlResult.setLayout(new java.awt.BorderLayout());

        jScrollPaneResult.setAutoscrolls(true);
        jScrollPaneResult.setEnabled(false);

        jtxaResult.setColumns(20);
        jtxaResult.setEditable(false);
        jtxaResult.setRows(5);
        jtxaResult.setTabSize(4);
        jScrollPaneResult.setViewportView(jtxaResult);

        jpnlResult.add(jScrollPaneResult, java.awt.BorderLayout.CENTER);
        //jtxaResult.setText(ep.getBatchResult(options.getTestFOLD()).toString());
        jtxaResult.setText(ep.getLastBatchResult().toString());
        jTabbedPane.addTab("Results E" + numberOfRuns, new CloseTabIcon(), jpnlResult);
        jTabbedPane.setSelectedComponent(jpnlResult);
        jTabbedPane.validate();
    }

    private void addBatchSelectedResultTab(EvolutionProcess ep) {
        JPanel jpnlResult = new JPanel();
        JScrollPane jScrollPaneResult = new JScrollPane();
        JTextArea jtxaResult = new JTextArea();
        jpnlResult.setLayout(new java.awt.BorderLayout());

        jScrollPaneResult.setAutoscrolls(true);
        jScrollPaneResult.setEnabled(false);

        jtxaResult.setColumns(20);
        jtxaResult.setEditable(false);
        jtxaResult.setRows(5);
        jtxaResult.setTabSize(4);
        jScrollPaneResult.setViewportView(jtxaResult);

        jpnlResult.add(jScrollPaneResult, java.awt.BorderLayout.CENTER);
        jtxaResult.setText(ep.getSelectedResult(options.getTestFOLD()).toString());

        jTabbedPane.addTab("Res. Sel. E" + numberOfRuns, new CloseTabIcon(), jpnlResult);
        jTabbedPane.setSelectedComponent(jpnlResult);
        jTabbedPane.validate();
    }

    private JPanel addSummaryTab(EvolutionProcess ep) {
        JPanel jpnlResult = new JPanel();
        JScrollPane jScrollPaneResult = new JScrollPane();
        JTextArea jtxaResult = new JTextArea();
        jpnlResult.setLayout(new java.awt.BorderLayout());

        jScrollPaneResult.setAutoscrolls(true);
        jScrollPaneResult.setEnabled(false);

        jtxaResult.setColumns(20);
        jtxaResult.setEditable(false);
        jtxaResult.setRows(5);
        jtxaResult.setTabSize(4);
        jScrollPaneResult.setViewportView(jtxaResult);

        jpnlResult.add(jScrollPaneResult, java.awt.BorderLayout.CENTER);
        jtxaResult.setText(ep.getSummary());


        jTabbedPane.addTab("Summary " + numberOfRuns, new CloseTabIcon(), jpnlResult);
        jTabbedPane.setSelectedComponent(jpnlResult);
        jTabbedPane.validate();
        return jpnlResult;
    }

    private JPanel addSelectedSummaryTab(EvolutionProcess ep) {
        JPanel jpnlResult = new JPanel();
        JScrollPane jScrollPaneResult = new JScrollPane();
        JTextArea jtxaResult = new JTextArea();
        jpnlResult.setLayout(new java.awt.BorderLayout());

        jScrollPaneResult.setAutoscrolls(true);
        jScrollPaneResult.setEnabled(false);

        jtxaResult.setColumns(20);
        jtxaResult.setEditable(false);
        jtxaResult.setRows(5);
        jtxaResult.setTabSize(4);
        jScrollPaneResult.setViewportView(jtxaResult);

        jpnlResult.add(jScrollPaneResult, java.awt.BorderLayout.CENTER);
        jtxaResult.setText(ep.getSummaryForSelectedGPs());

        jTabbedPane.addTab("SelectedGPSummary " + numberOfRuns, new CloseTabIcon(), jpnlResult);
        jTabbedPane.setSelectedComponent(jpnlResult);
        jTabbedPane.validate();
        return jpnlResult;
    }

    private void showSimplificationTab() {
        String title = jTabbedPane.getTitleAt(jTabbedPane.getSelectedIndex());
        jTabbedPane.addTab("S(" + title + ")", new CloseTabIcon(), lastSimpPanel);
        jTabbedPane.setSelectedComponent(lastSimpPanel);
        jTabbedPane.validate();
    }

    private void initSimplificationTab() {
        if (lastSimpPanel != null) {
            ep.removeSimplificationListener(lastSimpPanel);
        }
        lastSimpPanel = new TreePanel(null, "",ep.getEnvironment().getErrorCalculator());
        lastSimpPanel.setModified(true);
        ep.addSimplificationListener(lastSimpPanel);
    }

    private void setRuningModeOnButtons() {
        jbtnSimplify.setEnabled(false);
        jbtnStart.setEnabled(false);
        jbtnStop.setEnabled(true);
        jbtnSave.setEnabled(false);
    }

    private void setStopModeOnButtons() {
        jbtnSimplify.setEnabled(true);
        jbtnStart.setEnabled(true);
        jbtnStop.setEnabled(false);
        jbtnSave.setEnabled(true);
    }

    private void updateCurrentTab() {
        int panel = jTabbedPane.getSelectedIndex();
        if (jTabbedPane.getSelectedComponent() instanceof TreePanel) {
            TreePanel jp = (TreePanel) jTabbedPane.getComponent(panel);//getTabComponentAt(panel);
            jp.update();
        }
    }

    private void saveSelectedGPTab() {
        GP gp = ((TreePanel) jTabbedPane.getSelectedComponent()).getGP();
        ((TreePanel) jTabbedPane.getSelectedComponent()).setModified(true);
        FileOutputHandler f = new FileOutputHandler(options);
        Component c = this.getParent();
        while (c.getParent() != null) {
            c = c.getParent();
        }
        FileDialog jf = new FileDialog((JFrame) c, "Save tab", FileDialog.SAVE);
        jf.setDirectory(options.getDATA_FILE());
        jf.setVisible(true);
        if (jf.getFile() != null) {
            try {
                f.openFile(jf.getDirectory() + jf.getFile());
                f.printString(options.toString());
                f.printString(gp.getStatisticsAsString());
                f.printString(gp.getFormatedTree());
                f.printString("\n----------Testset output---------------\n");
                f.printString(gp.getGPTestPrediction());
                f.printString("\n----------TRAINset output---------------\n");
                f.printString(gp.getGPTrainPrediction());
                f.closeFile();
            } catch (GeneException ex) {
                ErrorManager.getInstance().reportError(ex);
            }
        }
    }

    public void saveSelectedTextAreaTab() {
        //   ((TreePanel) jTabbedPane.getSelectedComponent()).setModified(true);
        JPanel p = (JPanel) jTabbedPane.getSelectedComponent();
        JScrollPane s = (JScrollPane) p.getComponent(0);
        JTextArea ta = (JTextArea) s.getViewport().getComponent(0);
        Component c = this.getParent();
        while (c.getParent() != null) {
            c = c.getParent();
        }
        FileDialog jf = new FileDialog((JFrame) c, "Save tab", FileDialog.SAVE);
        jf.setDirectory(options.getDATA_FILE());
        jf.setVisible(true);

        FileOutputHandler f = new FileOutputHandler(options);
        if (jf.getFile() != null) {
            f.openFile(jf.getDirectory() + jf.getFile());
            f.printString(ta.getText());
            f.closeFile();
        }
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    public void evolutionStarted(EvolutionProcess source) {

        jpgbProgress.setMaximum(options.getGENERATIONS() * options.getBATCH_SIZE());
        jpgbProgress.setValue(0);
        if (options.isSIMPLIFICATION()) {
            initSimplificationTab();
        }
        numberOfRuns++;

        String title = options.getTestFOLD() + " E:" + numberOfRuns;
        if (options.getBATCH_SIZE() > 1) {
            title += " B:1";
        }
        addNewEvolutionTab(title);
        addNewPerformanceTab(title);
        setRuningModeOnButtons();
    }

    public void generationTerminated(EvolutionProcess source) {
        jpgbProgress.setValue(options.getGENERATIONS() * (source.getCurrentBatch() - 1) + source.getCurrentGeneration());
    }

    public void batchTerminated(EvolutionProcess source) {
        if (source.getCurrentBatch() != options.getBATCH_SIZE()) {
            String title = options.getTestFOLD() + " E:" + numberOfRuns + " B:" + (source.getCurrentBatch() + 1);
            addNewEvolutionTab(title);
        }

    }

    public void evolutionTerminated(EvolutionProcess source) {
        setStopModeOnButtons();
        //  addBatchSelectedResultTab(source);
    //    addBatchResultTab(source);
        this.setVisible(false);
        this.dispose();
    }

    public void evolutionProcessTerminated(EvolutionProcess source) {
        JPanel normSum = addSummaryTab(ep);
        JScrollPane s = (JScrollPane) normSum.getComponent(0);
        JTextArea ta = (JTextArea) s.getViewport().getComponent(0);
        if (options.isAUTO_SAVE()) {
            FileOutputHandler f = new FileOutputHandler();
            FileOutputHandler self = new FileOutputHandler();
            Calendar c = Calendar.getInstance();
            String d = "";
            d += c.get(Calendar.YEAR);
            d += c.get(Calendar.MONTH) + 1;
            d += c.get(Calendar.DAY_OF_MONTH);
            d += "-";
            d += c.get(Calendar.HOUR_OF_DAY);
            d += c.get(Calendar.MINUTE);
            d += c.get(Calendar.SECOND);
            if (!this.getTitle().contains(File.separator)) {
                f.openFile("." + File.separatorChar + "Results" + File.separator + "Summary for " + this.getTitle() + d + ".txt");
                //self.openFile("."+File.separatorChar+"Results"+File.separator+"Selected Summary for " + this.getTitle() + d + ".txt");
            } else {
                String[] sn = this.getTitle().split(File.separator);
                f.openFile("." + File.separatorChar + "Results" + File.separator + "Summary for " + sn[sn.length - 1] + d + ".txt");
                // self.openFile("."+File.separatorChar+"Results"+File.separator+"Selected"+sn[sn.length-1] + d + ".txt");
            }
            f.printString(ta.getText());
            // self.printString(selTa.getText());
            f.closeFile();
            // self.closeFile();
        }
        if (options.getRECIPIENTS().length() != 0) {
            try {
                GoogleMailer.sendSSLMessage(options.getRECIPIENTS(), "Summary for " + this.getTitle() + options.getFITNESS_FUNCTION() + ".txt", ta.getText());
            } catch (MessagingException ex) {
                ErrorManager.getInstance().reportError(ex);
            }

        }
       // this.setVisible(false);
       // this.dispose();
    }

    public void simplificationStarted(Simplyfier source) {
        showSimplificationTab();
        jpgbProgress.setMaximum(options.getSIMPLIFICATION_BATCH() * options.getSIMPLIFICATION_GENERATIONS());
        jpgbProgress.setValue(0);

    }

    public void simplificationGenerationTerminated(Simplyfier source) {
        jpgbProgress.setValue(options.getSIMPLIFICATION_GENERATIONS() * (source.getCurrentBatch() - 1) + source.getCurrentGeneration());


    }

    public void simplifictionTerminated(Simplyfier source) {
        setStopModeOnButtons();
    }

    // <editor-fold defaultstate="collapsed" desc="Generated Code">
    private void initComponents() {

        jpnlButtons = new javax.swing.JPanel();
        jbtnOptimize = new javax.swing.JButton();
        jbtnShowPrediction = new javax.swing.JButton();
        jbtnSave = new javax.swing.JButton();
        jbtnSimplify = new javax.swing.JButton();
        jbtnStop = new javax.swing.JButton();
        jbtnStart = new javax.swing.JButton();
        jpgbProgress = new javax.swing.JProgressBar();
        jTabbedPane = new javax.swing.JTabbedPane();
        jpnlTabOptions = new javax.swing.JPanel();
        jScrollPane1 = new javax.swing.JScrollPane();
        jtxaOptions = new javax.swing.JTextArea();


        setResizable(true);

        setPreferredSize(new java.awt.Dimension(116, 200));

        setVisible(true);

        addComponentListener(new java.awt.event.ComponentAdapter() {

            public void componentResized(java.awt.event.ComponentEvent evt) {
                formComponentResized(evt);
            }
        });

        jpnlButtons.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.RIGHT));

        jbtnOptimize.setText("Optimize");
        jbtnOptimize.addActionListener(new java.awt.event.ActionListener() {

            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jbtnOptimizeActionPerformed(evt);
            }
        });
        jpnlButtons.add(jbtnOptimize);

        jbtnShowPrediction.setText("Show Prediction"); // NOI18N
        jbtnShowPrediction.addActionListener(new java.awt.event.ActionListener() {

            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jbtnShowPredictionActionPerformed(evt);
            }
        });
        jpnlButtons.add(jbtnShowPrediction);

        jbtnSave.setText("Save"); // NOI18N
        jbtnSave.addActionListener(new java.awt.event.ActionListener() {

            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jbtnSaveActionPerformed(evt);
            }
        });
        jpnlButtons.add(jbtnSave);

        jbtnSimplify.setText("Simplify"); // NOI18N
        jbtnSimplify.setEnabled(false);
        jbtnSimplify.addActionListener(new java.awt.event.ActionListener() {

            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jbtnSimplifyActionPerformed(evt);
            }
        });
        jpnlButtons.add(jbtnSimplify);

        jbtnStop.setText("Stop"); // NOI18N
        jbtnStop.addActionListener(new java.awt.event.ActionListener() {

            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jbtnStopActionPerformed(evt);
            }
        });
        jpnlButtons.add(jbtnStop);

        jbtnStart.setText("Start"); // NOI18N
        jbtnStart.setDoubleBuffered(true);
        jbtnStart.addActionListener(new java.awt.event.ActionListener() {

            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jbtnStartActionPerformed(evt);
            }
        });
        jpnlButtons.add(jbtnStart);

        getContentPane().add(jpnlButtons, java.awt.BorderLayout.PAGE_END);
        getContentPane().add(jpgbProgress, java.awt.BorderLayout.PAGE_START);

        jTabbedPane.addChangeListener(new javax.swing.event.ChangeListener() {

            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                jTabbedPaneStateChanged(evt);
            }
        });

        jpnlTabOptions.setLayout(new java.awt.BorderLayout());

        jScrollPane1.setAutoscrolls(true);
        jScrollPane1.setEnabled(false);

        jtxaOptions.setColumns(20);
        jtxaOptions.setEditable(false);
        jtxaOptions.setRows(5);
        jScrollPane1.setViewportView(jtxaOptions);

        jpnlTabOptions.add(jScrollPane1, java.awt.BorderLayout.CENTER);

        jTabbedPane.addTab("Options", jpnlTabOptions);

        getContentPane().add(jTabbedPane, java.awt.BorderLayout.CENTER);

        setBounds(0, 0, 468, 342);
    }// </editor-fold>

    private void jbtnStopActionPerformed(java.awt.event.ActionEvent evt) {
        ep.stopEvolution();
        setStopModeOnButtons();
    }

    private void jbtnSimplifyActionPerformed(java.awt.event.ActionEvent evt) {

        setRuningModeOnButtons();
        initSimplificationTab();
        if (jTabbedPane.getSelectedComponent() instanceof TreePanel) {
            GP gp = ((TreePanel) jTabbedPane.getSelectedComponent()).getGP();
            ep.startSimplification(gp);
        }

    }

    private void jbtnStartActionPerformed(java.awt.event.ActionEvent evt) {
        setRuningModeOnButtons();
        ep.startEvolution();
    }

    private void jbtnSaveActionPerformed(java.awt.event.ActionEvent evt) {
        if (jTabbedPane.getSelectedComponent() instanceof TreePanel) {
            saveSelectedGPTab();
        } else {
            saveSelectedTextAreaTab();
        }

    }

    private void formComponentResized(java.awt.event.ComponentEvent evt) {
        updateCurrentTab();
    }

    private void jTabbedPaneStateChanged(javax.swing.event.ChangeEvent evt) {
        updateCurrentTab();
    }

    private void formInternalFrameClosed(javax.swing.event.InternalFrameEvent evt) {
        ep.removeallEvoltuionListeners();
        ep.stopEvolution();

    }

    private void jbtnShowPredictionActionPerformed(java.awt.event.ActionEvent evt) {
        try {
            if (jTabbedPane.getSelectedComponent() instanceof TreePanel) {
                TreePanel tp = (TreePanel) jTabbedPane.getSelectedComponent();
                GraphWindow gw = new GraphWindow(tp.getGP(), ep);
                tp.setActionListener(gw);
                gw.setVisible(true);
            }
        } catch (GeneException ex) {
            ErrorManager.getInstance().reportError(ex);
        }
    }

    private void jbtnOptimizeActionPerformed(java.awt.event.ActionEvent evt) {
        if (jTabbedPane.getSelectedComponent() instanceof TreePanel) {
            addNewOptimizationTab((TreePanel) jTabbedPane.getSelectedComponent());

        }
    }

    private void formInternalFrameClosing(javax.swing.event.InternalFrameEvent evt) {
        // TODO add your handling code here:
    }
    // Variables declaration - do not modify
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JTabbedPane jTabbedPane;
    private javax.swing.JButton jbtnOptimize;
    private javax.swing.JButton jbtnSave;
    private javax.swing.JButton jbtnShowPrediction;
    private javax.swing.JButton jbtnSimplify;
    private javax.swing.JButton jbtnStart;
    private javax.swing.JButton jbtnStop;
    private javax.swing.JProgressBar jpgbProgress;
    private javax.swing.JPanel jpnlButtons;
    private javax.swing.JPanel jpnlTabOptions;
    private javax.swing.JTextArea jtxaOptions;
    // End of variables declaration
}
